package com.xkcyy.one.ai.common.tool.util;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.xkcyy.one.ai.llm.model.ToolDefinition;
import com.xkcyy.one.ai.llm.model.ToolDefinitionFunction;
import com.xkcyy.one.ai.llm.model.ToolDefinitionParameter;
import com.xkcyy.one.ai.llm.model.ToolDefinitionParameters;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 工具定义生成器
 * 通过反射自动生成工具定义信息
 */
@Slf4j
public final class ToolDefinitionGenerator {
    private static final ObjectMapper objectMapper = new ObjectMapper();

    private ToolDefinitionGenerator() {
    }

    /**
     * 生成工具定义信息
     *
     * @param toolClass 工具类
     * @return 工具定义
     */
    public static ToolDefinition generate(Class<?> toolClass) {
        try {
            // 创建工具函数定义
            ToolDefinitionFunction function = ToolDefinitionFunction.builder()
                    .name(getToolName(toolClass))
                    .description(getToolDescription(toolClass))
                    .parameters(generateParameters(toolClass))
                    .build();

            // 创建工具定义
            return ToolDefinition.builder()
                    .type("function")
                    .function(function)
                    .build();
        } catch (Exception e) {
            log.error("Failed to generate tool definition for class: {}", toolClass.getName(), e);
            throw new RuntimeException("Failed to generate tool definition", e);
        }
    }

    /**
     * 获取工具名称
     */
    private static String getToolName(Class<?> toolClass) {
        // 尝试获取工具名称方法
        try {
            Method getNameMethod = toolClass.getMethod("getToolName");
            if (getNameMethod != null && Modifier.isPublic(getNameMethod.getModifiers())) {
                Object instance = toolClass.getDeclaredConstructor().newInstance();
                return (String) getNameMethod.invoke(instance);
            }
        } catch (Exception ignored) {
            // 忽略异常，使用默认名称
        }
        return toolClass.getSimpleName();
    }

    /**
     * 获取工具描述
     */
    private static String getToolDescription(Class<?> toolClass) {
        // 尝试获取工具描述方法
        try {
            Method getDescriptionMethod = toolClass.getMethod("getToolDescription");
            if (getDescriptionMethod != null && Modifier.isPublic(getDescriptionMethod.getModifiers())) {
                Object instance = toolClass.getDeclaredConstructor().newInstance();
                return (String) getDescriptionMethod.invoke(instance);
            }
        } catch (Exception ignored) {
            // 忽略异常，使用默认描述
        }
        return "A tool for " + getToolName(toolClass);
    }

    /**
     * 生成参数定义
     */
    private static ToolDefinitionParameters generateParameters(Class<?> toolClass) {
        try {
            // 获取泛型参数类型
            Class<?> argumentsClass = getArgumentsClass(toolClass);
            if (argumentsClass == null) {
                return ToolDefinitionParameters.builder()
                        .type("object")
                        .properties(new HashMap<>())
                        .required(new ArrayList<>())
                        .build();
            }

            Map<String, ToolDefinitionParameter> properties = new HashMap<>();
            List<String> required = new ArrayList<>();

            // 获取所有字段
            for (Field field : argumentsClass.getDeclaredFields()) {
                // 跳过静态字段和final字段
                if (Modifier.isStatic(field.getModifiers()) || Modifier.isFinal(field.getModifiers())) {
                    continue;
                }

                ToolDefinitionParameter parameter = ToolDefinitionParameter.builder()
                        .name(field.getName())
                        .type(getJsonSchemaType(field.getType()))
                        .description(getFieldDescription(toolClass, field))
                        .required(isFieldRequired(toolClass, field))
                        .build();
                properties.put(field.getName(), parameter);
                if (isFieldRequired(toolClass, field)) {
                    required.add(field.getName());
                }
            }

            return ToolDefinitionParameters.builder()
                    .type("object")
                    .properties(properties)
                    .required(required)
                    .build();
        } catch (Exception e) {
            log.error("Failed to generate parameters", e);
            throw new RuntimeException("Failed to generate parameters", e);
        }
    }

    /**
     * 获取泛型参数类型
     */
    private static Class<?> getArgumentsClass(Class<?> toolClass) {
        try {
            if (toolClass.getGenericSuperclass() instanceof ParameterizedType) {
                ParameterizedType parameterizedType = (ParameterizedType) toolClass.getGenericSuperclass();
                return (Class<?>) parameterizedType.getActualTypeArguments()[0];
            }
        } catch (Exception e) {
            log.warn("Failed to get arguments class", e);
        }
        return null;
    }

    /**
     * 获取字段描述
     */
    private static String getFieldDescription(Class<?> toolClass, Field field) {
        // 尝试获取字段描述方法
        try {
            Method getFieldDescriptionMethod = toolClass.getMethod("getFieldDescription", String.class);
            if (getFieldDescriptionMethod != null && Modifier.isPublic(getFieldDescriptionMethod.getModifiers())) {
                Object instance = toolClass.getDeclaredConstructor().newInstance();
                return (String) getFieldDescriptionMethod.invoke(instance, field.getName());
            }
        } catch (Exception ignored) {
            // 忽略异常，使用默认描述
        }
        return field.getName();
    }

    /**
     * 判断字段是否必需
     */
    private static boolean isFieldRequired(Class<?> toolClass, Field field) {
        // 尝试获取字段是否必需方法
        try {
            Method isFieldRequiredMethod = toolClass.getMethod("isFieldRequired", String.class);
            if (isFieldRequiredMethod != null && Modifier.isPublic(isFieldRequiredMethod.getModifiers())) {
                Object instance = toolClass.getDeclaredConstructor().newInstance();
                return (Boolean) isFieldRequiredMethod.invoke(instance, field.getName());
            }
        } catch (Exception ignored) {
            // 忽略异常，使用默认值
        }
        return true;
    }

    /**
     * 获取JSON Schema类型
     */
    private static String getJsonSchemaType(Class<?> type) {
        if (type == String.class) {
            return "string";
        } else if (type == Integer.class || type == Long.class || type == Short.class || type == Byte.class) {
            return "integer";
        } else if (type == Float.class || type == Double.class) {
            return "number";
        } else if (type == Boolean.class) {
            return "boolean";
        } else if (type.isArray() || List.class.isAssignableFrom(type)) {
            return "array";
        } else {
            return "object";
        }
    }
} 